/******************************************************************************
 * Copyright 2007 - 2021 Realtek Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/
 
#ifndef __HARMONY_OSDEP_SERVICE_H_
#define __HARMONY_OSDEP_SERVICE_H_

#ifdef __cplusplus
extern "C" {
#endif
/*include*/
#include "harmony_types.h"
#include "rtw_proc.h"

//#define RTW_CMD_THREAD_PRIORITY 4
#define RTW_CMD_THREAD_PRIORITY OSAL_THREAD_PRI_DEFAULT
#define RTW_CMD_THREAD_STACK_SIZE 0x2000 // 4 k

//#define RTW_XMIT_THREAD_PRIORITY 5
#define RTW_XMIT_THREAD_PRIORITY OSAL_THREAD_PRI_HIGH
#define RTW_XMIT_STACK_SIZE 0x2000

//#define RTW_RECV_THREAD_PRIORITY 5
#define RTW_RECV_THREAD_PRIORITY OSAL_THREAD_PRI_HIGH
#define RTW_RECV_STACK_SIZE 0x2000

//#define RTW_RECV_THREAD_PRIORITY 2
//#define RTW_RECV_STACK_SIZE 0x2000

/*normal*/
#ifdef CONFIG_DEBUG
#define DBG_TRACE(fmt, args...)		dprintf("\n\r[%s] " fmt, __FUNCTION__, ## args)
#define DBG_INFO(fmt, args...)		dprintf("\n\r[%s] " fmt, __FUNCTION__, ## args)
#else
#define DBG_TRACE(fmt, args...)
#define DBG_INFO(fmt, args...)
#endif
#define DBG_ERR(fmt, args...)		dprintf("\n\r[%s] " fmt, __FUNCTION__, ## args)

#define SET_MODULE_OWNER(some_struct)	do { } while (0)
#define SET_NETDEV_DEV(dev, obj)	do { } while (0)
#define register_netdev(dev)		(0)
#define unregister_netdev(dev)		do { } while (0)
#define netif_queue_stopped(dev)	(0)
#if (LOSCFG_KERNEL_SMP ==1)
#define netif_wake_queue(dev)		do { } while (0)
#endif
#define rtw_signal_process(pid, sig)	do { } while (0)




struct rtw_timer_list {
	struct timer_list timer;
	void (*function)(void *);
	void *arg;
};

typedef unsigned long systime;

extern void _rtw_spinlock_init(_lock *plock);

/*common define*/
static inline unsigned char *skb_tail_pointer(const struct sk_buff *skb)
{
	return skb->tail;
}

static inline void skb_reset_tail_pointer(struct sk_buff *skb)
{
	skb->tail = skb->data;
}

static inline void skb_reset_mac_header(struct sk_buff *skb)
{
	skb->mac_header = skb->data - skb->head;
}

static inline void skb_set_tail_pointer(struct sk_buff *skb, const int offset)
{
	skb->tail = skb->data + offset;
}
static inline unsigned char *skb_end_pointer(const struct sk_buff *skb)
{
	return skb->end;
}


//#define skb_tail_pointer(skb)	skb->tail
static inline unsigned char *skb_put(struct sk_buff *skb, unsigned int len)
{
	unsigned char *tmp = skb_tail_pointer((const struct sk_buff *)skb);
	//SKB_LINEAR_ASSERT(skb);
	skb->tail += len;
	skb->len  += len;
	return tmp;
}

static unsigned char *skb_push(struct sk_buff *skb, unsigned int len)
{
	skb->data -= len;
	skb->len  += len;
	return skb->data;
}
static inline unsigned char *__skb_pull(struct sk_buff *skb, unsigned int len)
{
	skb->len -= len;
	//if(skb->len < skb->data_len)
	//	printf("%s(),%d,error!\n",__FUNCTION__,__LINE__);
	return skb->data += len;
}
static inline unsigned char *skb_pull(struct sk_buff *skb, unsigned int len)
{
	if (len > skb->len)
		return NULL;

	return __skb_pull(skb, len);
}
static inline u32 skb_queue_len(const struct sk_buff_head *list_)
{
	return list_->qlen;
}
static inline void __skb_insert(struct sk_buff *newsk,
				struct sk_buff *prev, struct sk_buff *next,
				struct sk_buff_head *list)
{
	newsk->next = next;
	newsk->prev = prev;
	next->prev  = prev->next = newsk;
	list->qlen++;
}
static inline void __skb_queue_before(struct sk_buff_head *list,
				      struct sk_buff *next,
				      struct sk_buff *newsk)
{
	__skb_insert(newsk, next->prev, next, list);
}
static inline void skb_queue_tail(struct sk_buff_head *list,
				   struct sk_buff *newsk)
{
	mtx_lock(&list->lock);
	__skb_queue_before(list, (struct sk_buff *)list, newsk);
	mtx_unlock(&list->lock);
}
static inline struct sk_buff *skb_peek(struct sk_buff_head *list_)
{
	struct sk_buff *list = ((struct sk_buff *)list_)->next;
	if (list == (struct sk_buff *)list_)
		list = NULL;
	return list;
}
static inline void __skb_unlink(struct sk_buff *skb, struct sk_buff_head *list)
{
	struct sk_buff *next, *prev;

	list->qlen--;
	next	   = skb->next;
	prev	   = skb->prev;
	skb->next  = skb->prev = NULL;
	next->prev = prev;
	prev->next = next;
}

static inline struct sk_buff *skb_dequeue(struct sk_buff_head *list)
{
	mtx_lock(&list->lock);

	struct sk_buff *skb = skb_peek(list);
	if (skb)
		__skb_unlink(skb, list);

	mtx_unlock(&list->lock);

	return skb;
}
static inline void skb_reserve(struct sk_buff *skb, int len)
{
	skb->data += len;
	skb->tail += len;
}
static inline void __skb_queue_head_init(struct sk_buff_head *list)
{
	list->prev = list->next = (struct sk_buff *)list;
	list->qlen = 0;
}
/*
 * This function creates a split out lock class for each invocation;
 * this is needed for now since a whole lot of users of the skb-queue
 * infrastructure in drivers have different locking usage (in hardirq)
 * than the networking core (in softirq only). In the long run either the
 * network layer or drivers should need annotation to consolidate the
 * main types of usage into 3 classes.
 */
static inline void skb_queue_head_init(struct sk_buff_head *list)
{
	_rtw_spinlock_init(&list->lock);
	__skb_queue_head_init(list);
}

unsigned long copy_from_user(void *to, const void *from, unsigned long n);
unsigned long copy_to_user(void *to, const void *from, unsigned long n);
struct sk_buff * dev_alloc_skb(unsigned int size);
struct sk_buff *skb_clone(const struct sk_buff *skb);
struct sk_buff *skb_copy(const struct sk_buff *skb);
void dev_kfree_skb_any(struct sk_buff *skb);
/*skb porting end*/

static inline void _init_workitem(_workitem *pwork, void *pfunc, void *cntx)
{
	INIT_WORK(pwork, pfunc);
}

inline static void _set_workitem(_workitem *pwork)
{
	schedule_work(pwork);
}

inline static void _cancel_workitem_sync(_workitem *pwork)
{
	cancel_work_sync(pwork);
}

inline static int time_after(u32 now, u32 old)
{
	return (old < now);
}

struct net_device *alloc_etherdev(int sizeof_priv);

void free_netdev(struct net_device *dev);

int dev_alloc_name(struct net_device *net_dev, const char *ifname);

#endif
